<?php

/**
 * Web Image
 *
 */
class WSB_Image extends WSB_Fileinfo
{

	const MAX_WIDTH	 = 600;
	const MAX_HEIGHT = 600;

	/**
	 * @var integer
	 */
	private $_width;

	/**
	 * @var integer
	 */
	private $_height;

	/**
	 * @var string
	 */
	private $_cacheDir;

	/**
	 * @var string
	 */
	private $_md5File;

	/**
	 * @param integer $width
	 */
	public function setWidth($width)
	{
		$this->_width = intval($width);
	}

	/**
	 * @return integer
	 */
	public function getWidth()
	{
		if(empty($this->_width)) {
			$this->_init();
		}
		return $this->_width;
	}

	/**
	 * @param integer $height
	 */
	public function setHeight($height)
	{
		$this->_height = intval($height);
	}

	/**
	 * @return integer
	 */
	public function getHeight()
	{
		if(empty($this->_height)) {
			$this->_init();
		}
		return $this->_height;
	}

	/**
	 * Gib ein skaliertes Bild-Objekt zurueck.
	 *
	 * @param integer $maxWidth
	 * @param integer $maxHeight
	 * @return WSB_Image
	 */
	public function getScaledImage($maxWidth=0, $maxHeight=0)
	{
		$absoluteDimensions = $this->_getAbsoluteDimensions($maxWidth, $maxHeight);

		// Falls die berechneten Dimensionen mit den Dimensionen des originalen
		// Bildes entsprechen, wird keine Skalierung vorgenommen.
		if(($this->getWidth() == $absoluteDimensions[0]) && ($this->getHeight() == $absoluteDimensions[1])) {
			return $this;
		}

		$pathname = $this->createCachedImage($absoluteDimensions[0], $absoluteDimensions[1]);

		// Skaliertes Bildpfad ist identisch mit dem orginialen Bildpfad
		// --> Skalierung ist fehlgeschlagen!
		if($pathname == $this->getPathname()) {
			$img = new self($pathname);
			$img->setWidth($absoluteDimensions[0]);
			$img->setHeight($absoluteDimensions[1]);
			return $img;
		} else {
			return new self($pathname);
		}
	}

	/**
	 * @param array $attributes
	 * @return string
	 */
	public function getHtml($attributes=array())
	{
		if($this->isFile()) {
			return $this->_getHtmlTag($this->getRelativePath(), $this->getWidth(), $this->getHeight(), $attributes);
		} else {
			return '';
		}
	}

	/**
	 * @return void
	 */
	private function _init()
	{
		$dimension = getimagesize($this->getPathname());
		$this->_width = $dimension['0'];
		$this->_height = $dimension['1'];
		$this->_cacheDir = WSB_APP_PATH . 'tmp/cache/images/';
	}

	/**
	 * @param integer $maxWidth
	 * @param integer $maxHeight
	 * @return array
	 */
	private function _getAbsoluteDimensions($maxWidth, $maxHeight)
	{

		// aus negativen eine positive Zahl machen
		if($maxWidth < 0) {
			$maxWidth = $maxWidth * -1;
		}
		if($maxHeight < 0) {
			$maxHeight = $maxHeight * -1;
		}
		// falls 0, max. wert nehmen
		if(empty($maxWidth)) {
			$maxWidth = self::MAX_WIDTH;
		}
		if(empty($maxHeight)) {
			$maxHeight = self::MAX_HEIGHT;
		}

		$maxWidth = min(self::MAX_WIDTH, $maxWidth);
		$maxHeight = min(self::MAX_HEIGHT, $maxHeight);

		if($this->getWidth() != 0 && $this->getHeight() != 0) {
			$v = min(min($maxWidth,$this->getWidth())/$this->getWidth(),min($maxHeight,$this->getHeight())/$this->getHeight());
		}
		else {
			$v = 1;
		}
		$absWidth = ceil($v*$this->getWidth());
		$absHeight = ceil($v*$this->getHeight());

		return array($absWidth, $absHeight);
	}

	/**
	 * Create a cached image and return the path of it.
	 * If this method fails, the path of the original image will be returned.
	 *
	 * @param integer $absWidth
	 * @param integer $absHeight
	 * @return string The path to the image
	 */
	private function createCachedImage($absWidth, $absHeight)
	{
		$this->_md5File = md5_file($this->getPathname());
		$cachedDirPath = $this->_cacheDir . $this->_md5File;
		$extension = $this->getExtension();
		$cachedImagePath = $cachedDirPath . '/' . basename($this->getPathname(), '.' . $extension) . '-' . $absWidth . 'x' . $absHeight . '.' . $extension;
		if(is_file($cachedImagePath) && is_readable($cachedImagePath)) {
			return $cachedImagePath;
		} else {
			if(!is_dir($cachedDirPath)) {
				mkdir($cachedDirPath);
			}
			if($this->_resizeImage($absWidth, $absHeight, $cachedImagePath)) {
				return $cachedImagePath;
			} else {
				return $this->getPathname();
			}
		}
	}

	/**
	 * @param string $src
	 * @param integer $width
	 * @param integer $height
	 * @param array $attributes
	 * @return string
	 */
	private function _getHtmlTag($src, $width, $height, $attributes=array())
	{
		$attrStr = '';
		// ALT-Text
		if(!isset($attributes['alt'])) {
			$attributes['alt'] = '';
		}
		foreach($attributes AS $key=>$value) {
			$attrStr .= sprintf(' %s="%s"', $key, $value);
		}
		return sprintf('<img src="%s" width="%d" height="%d"%s />', $src, $width, $height, $attrStr);
	}

	/**
	 * Resize an image (png/jpg/gif)
	 *
	 * @param integer $absWidth
	 * @param integer $absHeight
	 * @param string $cachedImagePath
	 * @return boolean Returns true if image was resized, false if not
	 */
	private function _resizeImage($absWidth, $absHeight, $cachedImagePath)
	{
		if(!function_exists('gd_info')) {
			WSB_Log::warn('GD library is not installed (or PHPs gdlib extension not loaded)');
			return false;
		}
		$thumb = NULL;
		switch($this->getMimeType()) {
			case 'image/png':
				$im	= imagecreatefrompng($this->getPathname());
				$thumb = $this->_resampleImage($im, $absWidth, $absHeight);
				imagepng($thumb, $cachedImagePath);
			break;
			case 'image/jpeg':
				$im	= imagecreatefromjpeg($this->getPathname());
				$thumb = $this->_resampleImage($im, $absWidth, $absHeight);
				imagejpeg($thumb, $cachedImagePath, 85);
			break;
			case 'image/gif':
				$im	= imagecreatefromgif($this->getPathname());
				$thumb = $this->_resampleImage($im, $absWidth, $absHeight);
				imagegif($thumb, $cachedImagePath);
			break;
			default:
		}
		imagedestroy($thumb);
		return true;
	}

	/**
	 * @param resource $resource
	 * @param integer $absWidth
	 * @param integer $absHeight
	 * @return resource
	 */
	private function _resampleImage($resource, $absWidth, $absHeight)
	{
		$img = ImageCreateTrueColor($absWidth, $absHeight);
		imagecopyresampled($img, $resource, 0, 0, 0, 0, $absWidth, $absHeight, $this->getWidth(), $this->getHeight());
		return $img;
	}

}

?>